package developer.zyk.ability.knowledge.parsers.fileParser;

import cn.hutool.json.JSONUtil;
import com.aliyun.docmind_api20220711.Client;
import com.aliyun.docmind_api20220711.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import developer.zyk.ability.knowledge.common.KnowledgeUploadStatus;
import developer.zyk.global.common.consts.FileType;
import developer.zyk.global.config.PlatFormProperties;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.ai.document.Document;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;

/**
 * @author zhangyongkang
 * @time 2025/5/15 14:09
 * @description
 */
@Component
public class GeneralFileParserHandler implements FileParserHandler {

    private List<String> statusList = List.of("success");
    @Resource
    private PlatFormProperties platFormProperties;

    int pageSize = 100;

    @Override
    public List<FileType> supportFileType() {
        return Arrays.stream(FileType.values()).toList();
    }

    @SneakyThrows
    @Override
    public List<Document> parse(File file, BiConsumer<KnowledgeUploadStatus, String> statusSync) {
        List<Document> result = new ArrayList<>();
        try {
            //step1 创建异步任务
            String taskId = createTask(file);
            statusSync.accept(KnowledgeUploadStatus.HANDLE, "");
            //step2 定时查询结果
            boolean flag;
            String status = "";
            int total = 0;
            do {
                QueryDocParserStatusResponse resp = searchStatus(taskId);
                status = resp.getBody().getData().getStatus();
                flag = isEnd(status);
                total = resp.getBody().getData().getNumberOfSuccessfulParsing();
            } while (flag);

            if ("success".equalsIgnoreCase(status)) {
                statusSync.accept(KnowledgeUploadStatus.EMBEDDING_SUCCESS, "");
                int pages = (total % pageSize == 0) ? total / pageSize : ((total / pageSize) + 1);
                for (int s = 0; s < pages; s++) {
                    result.addAll(getResult(taskId, s, pageSize));
                }
            } else {
                statusSync.accept(KnowledgeUploadStatus.EMBEDDING_FAILED, "");
            }
        } catch (Throwable e) {
            statusSync.accept(KnowledgeUploadStatus.EMBEDDING_FAILED, e.getMessage());
        }
        //step3 返回结果
        return result;
    }


    private Config getConfig() {
        PlatFormProperties.AliYun aliYun = platFormProperties.getAliYun();
        Config config = new Config()
                // 通过credentials获取配置中的AccessKey ID
                .setAccessKeyId(aliYun.getAccessId())
                // 通过credentials获取配置中的AccessKey Secret
                .setAccessKeySecret(aliYun.getAccessKey());
        config.endpoint = aliYun.getEndpoint();
        return config;
    }

    private String createTask(File file) throws Exception {
        Config config = getConfig();
        Client client = new Client(config);
        // 创建RuntimeObject实例并设置运行参数
        RuntimeOptions runtime = new RuntimeOptions();
        SubmitDocParserJobAdvanceRequest advanceRequest = new SubmitDocParserJobAdvanceRequest();
        advanceRequest.fileUrlObject = new FileInputStream(file);
        advanceRequest.fileName = file.getName();
        // 发起请求并处理应答或异常。
        SubmitDocParserJobResponse response = client.submitDocParserJobAdvance(advanceRequest, runtime);
        return response.getBody().getData().getId();
    }

    private QueryDocParserStatusResponse searchStatus(String id) throws Exception {
        Client client = new Client(getConfig());
        QueryDocParserStatusRequest resultRequest = new QueryDocParserStatusRequest();
        resultRequest.id = id;
        return client.queryDocParserStatus(resultRequest);
    }

    private boolean isEnd(String status) {
        return statusList.stream()
                .noneMatch(a -> a.equalsIgnoreCase(status));
    }

    private List<Document> getResult(String requestId, int page, int pageSize) throws Exception {
        Client client = new Client(getConfig());
        GetDocParserResultRequest resultRequest = new GetDocParserResultRequest();
        resultRequest.id = requestId;
        resultRequest.layoutStepSize = pageSize;
        resultRequest.layoutNum = page;
        GetDocParserResultResponse response = client.getDocParserResult(resultRequest);
        return Optional.ofNullable(
                        response.getBody().getData().get("layouts")
                ).map(a -> {
                    return (List<?>) a;
                })
                .orElse(new ArrayList<>())
                .stream()
                .map(a -> JSONUtil.toBean(JSONUtil.toJsonStr(a), Layout.class))
                .map(a -> new Document(a.getMarkdownContent()))
                .toList();

    }

    @Data
    public static class Layout {
        private Integer level;
        private Integer index;
        private String markdownContent;
        private String text;
    }
}
